package com.turing.comment.service.impl;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.jwt.JWTUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.turing.comment.entity.Comment;
import com.turing.comment.feign.*;
import com.turing.comment.service.CommentService;
import com.turing.comment.mapper.CommentMapper;
import enums.ErrorCode;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
import result.Result;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.swing.text.DateFormatter;
import java.math.BigDecimal;
import java.util.*;

/**
 * @author admin
 * @description 针对表【comment(评论)】的数据库操作Service实现
 * @createDate 2023-05-08 14:29:25
 */
@Service
public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment>
        implements CommentService {

    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private HttpServletRequest request;
    @Resource
    private AuthService authService;
    @Resource
    private SystemService systemService;
    @Resource
    private CustomerService customerService;
    @Resource
    private MerchantService merchantService;
    @Resource
    private MissionService missionService;

    /**
     * 40101评论列表(PC)
     */
    @Override
    public Result getCnList(String startTime, String endTime, String merchantName, String missionTitle, String cusNickname, Integer sortType, Integer orderType, Integer pageNum, Integer pageSize) {

//        DateTime startTime1 = DateUtil.parse(startTime);
//        DateTime endTime1 = DateUtil.parse(endTime);

        if (pageNum != null && pageSize != null) {
            PageHelper.startPage(pageNum, pageSize);
        }
        List<String> commentIds = new ArrayList<>();
        LinkedHashMap redisData = new LinkedHashMap();
        ZSetOperations zsetOps = redisTemplate.opsForZSet();
        Set<ZSetOperations.TypedTuple> redisSet;
//        System.out.println("zsetOps = " + zsetOps.rangeWithScores("likeCount",(pageNum - 1) * pageSize, pageNum * pageSize - 1));
        if (sortType == 1) {
            if (pageNum != null) {
                if (orderType == 1) {
                    redisSet = zsetOps.reverseRangeWithScores("likeCount", (pageNum - 1) * pageSize, pageNum * pageSize - 1);
                } else {
                    redisSet = zsetOps.rangeWithScores("likeCount", (pageNum - 1) * pageSize, pageNum * pageSize - 1);
                }
            } else {
                if (orderType == 1) {
                    redisSet = zsetOps.reverseRangeWithScores("likeCount", 0, -1);
                } else {
                    redisSet = zsetOps.rangeWithScores("likeCount", 0, -1);
                }
            }
            for (ZSetOperations.TypedTuple typedTuple : redisSet) {
                commentIds.add((String) typedTuple.getValue());
            }
            System.out.println("commentIds = " + commentIds);

        } else {
            redisSet = zsetOps.rangeWithScores("likeCount", 0, -1);
            for (ZSetOperations.TypedTuple typedTuple : redisSet) {
                redisData.put(typedTuple.getValue(), typedTuple.getScore());
            }
        }
        List<LinkedHashMap<String, Object>> list = this.baseMapper.getCnList(startTime, endTime, merchantName, missionTitle, cusNickname, sortType, orderType, commentIds);
        System.out.println("list = " + list);
        if (sortType != 1) {
            for (LinkedHashMap map : list) {
                map.put("likeCount", redisData.get(map.get("commentId")).toString().substring(0, redisData.get(map.get("commentId")).toString().length() - 2));
                System.out.println("map = " + map);
            }

        }
        if (list.size() > 0) {
            return Result.success(new PageInfo<>(list));
        } else {
            return Result.fail(ErrorCode.NODATA);
        }
    }

    /**
     * 40102评论详情(PC)
     */
    @Override
    public Result geCnById(String id) {
        LinkedHashMap<String, Object> map = this.baseMapper.getCnById(id);
        String commentImgList = (String) map.get("commentImgList");
        String[] commentImgs = commentImgList.split(",");
        map.put("commentImgList", commentImgs);
        if (ObjectUtil.isNotEmpty(map)) {
            return Result.success(map);
        } else {
            return Result.fail(ErrorCode.NODATA);
        }
    }


    /**
     * 1.1.3、40103评论详情(手机)
     */
    @Override
    public Result geCnByIdForPhone(String id) {
        //获取登录用户主键
        String cusId = getCusIdByToken();
        //查询已有字段
        LinkedHashMap<String, Object> cnMap = this.baseMapper.geCnByIdForPhone(id);
        //将图片路径按 "," 切分成数组 插入结果
        String commentImgList = (String) cnMap.get("commentImgList");
        String[] commentImgs = commentImgList.split(",");
        cnMap.put("commentImgList", commentImgs);


        //查询点赞数
        Integer likeCount = this.baseMapper.getLikeCount(id);
        cnMap.put("likeCount", likeCount);
        //查询商家评论总数
        Integer merchantComments = this.baseMapper.getMerchantComments(id);
        cnMap.put("merchantComments", merchantComments);

        //查询用户是否为当前评论点赞
        Integer count = this.baseMapper.getCcIdByCommentAndCus(id, cusId);
        if (count > 0) {
            cnMap.put("likeState", 1);
        }

        if (cnMap.get("missionId") != null) {
            String missionId = (String) cnMap.get("missionId");
            //任务领取总量
            Integer commentCount = this.baseMapper.getMiCount(missionId, null);
            cnMap.put("commentCount", commentCount);
            //任务领取状态
            Integer myMissonCount = this.baseMapper.getMiCount(missionId, cusId);
            if (myMissonCount > 0) {
                cnMap.put("myMissonState", 1);
                //任务完成状态
                Integer myMissonState = this.baseMapper.getMyMiStateByMiId(missionId, cusId);
                if (myMissonState > 0) {
                    cnMap.put("myCommentState", 1);
                }
                //任务签到状态
                Integer signState = this.baseMapper.getSignState(missionId, cusId);
                cnMap.put("signState", signState);
            } else {
                cnMap.put("myMissonState", 0);
            }
        }

        //评论回复总数
        Integer replyCount = this.baseMapper.getReplyCount(id);
        cnMap.put("replyCount", replyCount);
        if (replyCount > 0) {
            //回复列表
            List<LinkedHashMap<String, Object>> list = this.baseMapper.getReplyList(id);
            List replyList = new ArrayList<>();
            List messageList = new ArrayList<>();
            Map<String, Object> replyMap = new HashMap<>();
            Map<String, Object> messageMap = new HashMap<>();
            //遍历查出replyList和messageList的所有数据并装入新的map
            for (LinkedHashMap<String, Object> map : list) {
                String scId = map.get("scId").toString();
                replyMap.put("scId", scId);
                replyMap.put("scInfo", map.get("scInfo"));
                replyMap.put("likeCount", map.get("likeCount"));
                replyMap.put("createTime", map.get("createTime"));
                replyMap.put("cusImg", map.get("cusImg"));
                replyMap.put("cusNickname", map.get("cusNickname"));
                replyMap.put("cusPrestige", map.get("cusPrestige"));
                replyMap.put("cusLevel", map.get("cusLevel"));
                Integer likeScCount = this.baseMapper.getCcIdByCommentAndCus(scId, cusId);
                if (likeScCount > 0) {
                    replyMap.put("likeState", 1);
                } else {
                    replyMap.put("likeState", 0);
                }

                if (!scId.isEmpty()) {
                    List<LinkedHashMap<String, Object>> list1 = this.baseMapper.getMessageList(scId);
                    for (LinkedHashMap<String, Object> map1 : list1) {
                        String scId1 = map.get("scId").toString();
                        messageMap.put("scId", map1.get("scId"));
                        messageMap.put("scInfo", map1.get("scInfo"));
                        messageMap.put("likeCount", map1.get("likeCount"));
                        messageMap.put("createTime", map1.get("createTime"));
                        messageMap.put("cusNickname", map1.get("cusNickname"));
                        Integer likeScCount1 = this.baseMapper.getCcIdByCommentAndCus(scId1, cusId);
                        if (likeScCount1 > 0) {
                            messageMap.put("likeState", 1);
                        } else {
                            messageMap.put("likeState", 0);
                        }
                    }
                    messageList.add(messageMap);
                }

            }
            replyMap.put("messageList", messageList);
            replyList.add(replyMap);
            cnMap.put("replyList", replyList);
        } else {
            cnMap.put("replyList", new ArrayList<>());
        }

        SetOperations setOperations = redisTemplate.opsForSet();
        boolean isMember = setOperations.isMember("comment" + id, cusId);
        if (!isMember) {
            setOperations.add("comment" + id, cusId);
            Comment comment = baseMapper.selectById(id);
            comment.setCommentBrowse(comment.getCommentBrowse() + 1);
            baseMapper.updateById(comment);
        }

        if (ObjectUtil.isNotEmpty(cnMap)) {
            return Result.success(cnMap);
        } else {
            return Result.fail(ErrorCode.NODATA);
        }
    }


    /**
     * 通过token获取登录用户id
     */
    private String getCusIdByToken() {
        String token = request.getHeader("Authorization");
        String tokenHead = "Bearer ";
        token = token.substring(tokenHead.length());
        Result info = authService.getUserInfoByToken(token);
        String s = info.getData().toString();
//        return s.substring(10, s.length() - 1);
        return s.substring(s.lastIndexOf("=") + 1, s.lastIndexOf("}"));
    }

    /**
     * 测试验证通过token获取登录用户id
     */
    @Override
    public Result getCusId() {
        return Result.success(getCusIdByToken());
    }

    /**
     * 40107首页评论列表(手机)
     */
    @Override
    public Result dashCommentList(String cityId, Integer sortType, Integer orderType, Integer pageNum, Integer pageSize) {
        //获取登录用户主键
        String cusId = getCusIdByToken();
        //关注的人
        List<String> attCusIds = this.baseMapper.getAttCusId(cusId);
        //从redis里查出查询过的关注的人的评论主键集合
        SetOperations setOperations = redisTemplate.opsForSet();
        Set attComments = setOperations.members("comment::attComment");
        //关注的人的所有评论 选出五条
        List<LinkedHashMap> attComList = this.baseMapper.dashAttComList(cityId, sortType, orderType, cusId, attComments);
        //其他评论
        List<LinkedHashMap> commentList = this.baseMapper.dashComList(cityId, sortType, orderType, attCusIds);
        if (attComList.size() > 0) {
            //遍历关注的人的所有评论 将已经查询过得关注的人的评论主键放入redis
            for (LinkedHashMap attComMap : attComList) {
                if (ObjectUtil.isNotEmpty(attComMap)) {
                    String attCommentId = (String) attComMap.get("commentId");
                    setOperations.add("comment::attComment", attCommentId);
                }
            }
        }

        LinkedHashMap redisData = new LinkedHashMap();
        ZSetOperations zsetOps = redisTemplate.opsForZSet();
        Set<ZSetOperations.TypedTuple> redisSet;

        redisSet = zsetOps.rangeWithScores("likeCount", 0, -1);
        if (sortType != 1) {
            if (pageNum != null && pageSize != null) {
                PageHelper.startPage(pageNum, pageSize);
            }
            for (ZSetOperations.TypedTuple typedTuple : redisSet) {
                redisData.put(typedTuple.getValue(), typedTuple.getScore());
            }

            for (LinkedHashMap comMap : commentList) {
                comMap.put("likeCount", redisData.get(comMap.get("commentId")).toString().substring(0, redisData.get(comMap.get("commentId")).toString().length() - 2));

            }
            for (LinkedHashMap comMap : attComList) {
                comMap.put("cusNickname", comMap.get("cusNickname") + "(你的关注)");
                comMap.put("likeCount", redisData.get(comMap.get("commentId")).toString().substring(0, redisData.get(comMap.get("commentId")).toString().length() - 2));

            }

            System.out.println("attCusId = " + attCusIds);
//            List<LinkedHashMap> list = new ArrayList<>();
//            list.addAll(attComList);
//            list.addAll(commentList);
            PageInfo pageInfo = new PageInfo<>(commentList);

            if (attComList.size() > 0) {
                return Result.success(pageInfo);
            } else {
                return Result.fail(ErrorCode.NODATA);

            }

        }


        ZSetOperations zsetOps1 = redisTemplate.opsForZSet();
        if (sortType == 1) {
            List<String> comIds = this.baseMapper.dashComIdsList(cityId, sortType, orderType, attCusIds);
            Set<ZSetOperations.TypedTuple> set;
            if (pageNum != null) {
                if (orderType == 1) {
                    set = zsetOps1.reverseRangeWithScores("likeCount", 0, -1);
                } else {
                    set = zsetOps1.rangeWithScores("likeCount", 0, -1);
                }
                int count = 0; //记录满足条件的评论主键数量
                int index0 = (pageNum - 1) * pageSize;
                List<String> resultCommentIdList = new ArrayList<>();
                for (ZSetOperations.TypedTuple typedTuple : set) {
                    String commentId = (String) typedTuple.getValue();
                    if (comIds.contains(commentId)) {
                        if (count >= index0 && resultCommentIdList.size() < pageSize) {
                            resultCommentIdList.add(commentId);
                        }
                        count++;
                    }
                    if (resultCommentIdList.size() == pageSize) {
                        break;
                    }
                }
                List<LinkedHashMap> comList = this.baseMapper.listByLikeCount(resultCommentIdList, orderType);
                attComList.addAll(comList);
                if (attComList.size() > 0) {
                    return Result.success(new PageInfo<>(attComList));
                } else {
                    return Result.fail(ErrorCode.NODATA);

                }
            }
        }


        return Result.success();
    }

    @Override
    public Result cnClose(String commentId) throws ParseException {
        Comment comment = this.baseMapper.selectById(commentId);
        //获得评论用户主键
        String cusId = comment.getCusId();
        List<String> list = new ArrayList<>();
        list.add(cusId);
        Object[] objects = list.toArray();
        // 对转换后的数组设置类型
        String[] cusIds = Arrays.copyOf(objects, objects.length, String[].class);
        // 获取评论时间
        Date commentTime = comment.getCommentTime();
        // 将结果格式化为指定字符串
        DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        String time = formatter.format(commentTime);
        // 修改评论赏金为0，评论状态为0
        comment.setCommentAmount(BigDecimal.valueOf(0));
        comment.setCommentState("0");


        //获取当前日期 用来加入到消息内容
//        Date now = new Date();
//        DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm");
//        DateFormat formatter1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        String format = formatter.format(now);
//        String format1 = formatter1.format(now);


        // 获取当前日期
        LocalDateTime currentDate = LocalDateTime.now();
        DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        String startTime = formatter1.format(currentDate);
        System.out.println("startTime = " + startTime);
        // 加 30 天
        LocalDateTime resultDate = currentDate.plusDays(30);
        // 将结果格式化为指定字符串
        DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String endTime = formatter2.format(resultDate);


        JSONObject message = new JSONObject();
        message.put("messageTitle", "无效评论");
        message.put("messageContent", "您在" + time + "发表的评论有违规。已变成无效评论");
        message.put("customerIds", cusIds);
        message.put("startTime", startTime);
        message.put("endTime", endTime);
        message.put("commentId", null);
        message.put("messageType", 0);
        systemService.addSave(message);
        int i = this.baseMapper.updateById(comment);
        if (i > 0) {
            return Result.success();
        } else {
            return Result.fail(1900, "评论关闭失败");
        }
    }

    /**
     * 40104评论修改(PC)
     */
    @Override
    public Result cnEdit(String commentId, String adminScore, String commentAmount, String cusInfo) throws ParseException {
        Comment comment = this.baseMapper.selectById(commentId);
        //获取任务id
        String missionId = comment.getMissionId();
        //获得"拉新分成比例"值
        JSONObject dicObject = JSON.parseObject(JSON.toJSONString(systemService.getDic("24", null).getData()));
        BigDecimal dicInfo = new BigDecimal(dicObject.getString("dicInfo"));
        //将传入的赏金转类型
        BigDecimal comAmount = new BigDecimal(String.valueOf(commentAmount));
        //老用户所能获得的赏金最小值（大于等于）
        BigDecimal decimal = BigDecimal.valueOf(0.01);
        //根据评论查找用户
        JSONObject customer = JSON.parseObject(JSON.toJSONString(customerService.geCusById(comment.getCusId()).getData()));
        //用户赏金余额
        BigDecimal cusAmount = customer.getBigDecimal("cusAmount");
        //上级用户id
        String resCusId = customer.getString("resCusId");


        //若cusInfo不为null，则更新客户信息
        if (cusInfo != null) {
            customer.put("cusInfo", cusInfo);
        }
        if (missionId != null) {
            //根据评论的任务主键获得任务
            JSONObject mission = JSON.parseObject(JSON.toJSONString(missionService.geMissionById(comment.getMissionId()).getData()));
            //根据任务获得任务剩余赏金余额
            BigDecimal leftAmount = mission.getBigDecimal("leftAmount");
            //任务剩余赏金余额和传入的赏金比较
            int i = leftAmount.compareTo(comAmount);
            if (i >= 0) {
                //如果剩余的大于等于传入的 按照传入的赏金进行发放
                updateComAmountOfCusAndRescus(dicInfo, comAmount, decimal, customer, cusAmount, resCusId);
                //修改任务赏金
                mission.put("leftAmount",leftAmount.subtract(comAmount));
            } else {
                //如果剩余的小于传入的 则将任务余额全部发放
                comAmount = leftAmount;
                updateComAmountOfCusAndRescus(dicInfo, comAmount, decimal, customer, cusAmount, resCusId);
                //修改任务赏金
                mission.put("leftAmount",BigDecimal.valueOf(0.00));
            }
            missionService.missonEdit(mission);
        }else {
            //根据评论查找商家
            JSONObject merchant = JSON.parseObject(JSON.toJSONString(merchantService.getMerById(comment.getMerchantId()).getData()));
            //根据商家获得任务剩余赏金余额
            BigDecimal leftAmount = merchant.getBigDecimal("leftAmount");
            //任务剩余赏金余额和传入的赏金比较
            int i = leftAmount.compareTo(comAmount);
            if (i >= 0) {
                //如果剩余的大于等于传入的 按照传入的赏金进行发放
                updateComAmountOfCusAndRescus(dicInfo, comAmount, decimal, customer, cusAmount, resCusId);
                //修改任务赏金
                merchant.put("leftAmount",leftAmount.subtract(comAmount));
            } else {
                //如果剩余的小于传入的 则将任务余额全部发放
                comAmount = leftAmount;
                updateComAmountOfCusAndRescus(dicInfo, comAmount, decimal, customer, cusAmount, resCusId);
                //修改任务赏金
                merchant.put("leftAmount",BigDecimal.valueOf(0.00));
            }
        }


        customerService.cusEdit(customer);


        JSONObject message = new JSONObject();
        message.put("messageContent", dicInfo);
        message.put("customerIds", dicInfo);
        message.put("startTime", dicInfo);
        message.put("endTime", dicInfo);
        message.put("commentId", null);
        message.put("messageType", 0);
        systemService.addSave(message);
        int i = this.baseMapper.updateById(comment);

        return Result.fail(-1, "ceshi");
    }





    /** 40108根据主键集合得到评论集合(手机) */
    @Override
    public Result listCommentByIds(String[] ids) {








        return null;
    }

    private void updateComAmountOfCusAndRescus(BigDecimal dicInfo, BigDecimal comAmount, BigDecimal decimal, JSONObject customer, BigDecimal cusAmount, String resCusId) {
        if (resCusId != null) {
            //根据用户查找上级用户
            JSONObject resCustomer = JSON.parseObject(JSON.toJSONString(customerService.geCusById(resCusId).getData()));
            //老用户赏金余额
            BigDecimal resCusAmount = resCustomer.getBigDecimal("cusAmount");
            //老用户能获得的赏金
            BigDecimal resAmount = comAmount.multiply(dicInfo);
            int i = resAmount.compareTo(decimal);
            //如果扣除金额大于0.01 扣除一部分赏金给上级用户
            if (i >= 0) {
                resCustomer.put("cusAmount", resCusAmount.add(resAmount));
                customerService.cusEdit(resCustomer);
                //修改该评论用户的赏金
                customer.put("cusAmount", cusAmount.add(comAmount.subtract(resAmount)));
            } else {
                customer.put("cusAmount", cusAmount.add(comAmount));
            }
        }
    }


}




